<?php

/**
 * SigmaCMS - Content Management System
 *
 * Copyright (C) 2008 Pavol Biely
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package    SigmaCMS
 * @author     Pavol Biely <pavolbiely@gmail.com>
 * @copyright  2008 Pavol Biely
 * @license    http://www.gnu.org/licenses/gpl.txt   GNU General Public License
 * @link       http://pabi3.com/
 * @since      0.1.0
 */

final class Main
{
	/**
	 * Constructor
	 * 
	 * @return void
	 */
	public function __construct()
	{
		try {
			// connect to database
			db::initialize();
	
			// load language
			i18n::language();
	
			// register installed and activated plugins
			Plugin::registerAll();
	
			// check actions
			Action::initialize();

		} catch (Sigma_Exception $e) {
			// terminate SigmaCMS
			die($e->getMessage());
		}
	}

	/**
	 * Destructor
	 *
	 * @return void
	 */
	public function __destruct()
	{
		// unregister all plugins
		Plugin::unregisterAll();

		// disconnect from database
		db::deInitialize();
	}

	/**
	 * Instance of Main class
	 *
	 * @var object
	 */
	static private $_instance = NULL;

	/**
	 * Singleton - create unique object
	 *
	 * @return object
	 */
	static public function initialize()
	{
		if (self::$_instance == NULL) {
			self::$_instance = new self;
		}
		return self::$_instance;
	}

	/**
	 * Add event to specified place
	 *
	 * @return void
	 */
	static public function addEvent()
	{
		// event parameters
		$params = func_get_args();

		// the first parameter must be set
		if (!isset($params[0])) {
			throw new Sigma_Exception('Event name was not defined.');
		}

		// instance of class Driver
		$ins = Parser::singleton()->getDriver();

		// call event
		call_user_func_array(array($ins,'parse_event'),$params);
	}

	///////////////////////////////// skins /////////////////////////////////////

	/**
	 * Skin sufix
	 *
	 */
	const SKIN_SUFFIX = '.tpl';

	/**
	 * Currently selected skin
	 * 
	 * @var string
	 */
	static public $skin;

	/**
	 * Set skin (this method can be called 1x from some "action")
	 *
	 * @param string $skin
	 * @return void
	 */
	static public function setSkin($skin)
	{
		if (self::$skin) {
			$skin = self::$skin;
		} else {
			self::$skin = Media::clearPath($skin);
		}
	}

	/**
	 * Use selected skin
	 *
	 * @param string $skin
	 * @return void
	 */
	static public function select($skin)
	{
		// set skin
		self::setSkin(&$skin);

		// path to skin
		$skinPath = cfg::DIR_SKINS.cfg::get('skin').$skin.self::SKIN_SUFFIX;

		// does the skin file exist?
		if (is_file($skinPath)) {
			// directory name of skin
			$skinDirName = rtrim(cfg::get('skin'), '/');

			// load MIME type
			$ctype = db::fQuery("SELECT `ctype` FROM ".db::prefix('skins')." WHERE `id`='".db::escape($skin)."' AND `skin`='".db::escape($skinDirName)."'");

			// send headers
			if (!headers_sent()) {
				// author & generator
				header('Generator: SigmaCMS');
				header('Author: Pavol Biely, http://pabi3.com/');

				// send Content-Type
				self::sendContentType($ctype);
			}

			// skin content
			$skinCode = file_get_contents($skinPath);

			// Parser instance
			$parser = Parser::singleton();

			// default keywords
			$parser->addKeyword('h1',cfg::get('h1'));
			$parser->addKeyword('title',cfg::get('title'));
			$parser->addKeyword('language',cfg::get('language'));
			$parser->addKeyword('description',cfg::get('description'));
			$parser->addKeyword('keywords',cfg::get('keywords'));

			// events before skin
			self::addEvent('preSkin');

			// analyze skin content
			$parser->analyze($skinCode);

			// events after skin
			self::addEvent('posSkin');
		} else {
			// page was not found
			header('HTTP/1.1 404 Not Found');
			header('Location:'.cfg::URL.'404.html');
			exit;
		}
	}

	/**
	 * Send Content-Type header
	 *
	 * @param string $contentType
	 * @return void
	 */
	static public function sendContentType($contentType = NULL)
	{
		switch ($contentType) {
			case 'application/xhtml+xml':
				// does the client's browser accept application/xhtml+xml?
				if (isset($_SERVER['HTTP_ACCEPT']) && stristr(_server('HTTP_ACCEPT'), $contentType)) {
					// send headers
					header('Content-Type: '.$contentType.'; charset=utf-8');
					header('Vary: Accept');
					break;
				}

			case 'text/html':
				header('Content-Type: text/html; charset=utf-8');
				break;

			default:
				// remove dangerous characters
				$contentType = str_replace(array("\n","\r"), NULL, $contentType);

				// send header
				header('Content-Type: '.$contentType.'; charset=utf-8');
				header('Vary: Accept');
				break;
		}
	}

	/**
	 * Check if skin exists
	 *
	 * @param string $skin
	 * @return boolean
	 */
	static public function skinExists($skin)
	{
		// remove unnecessary characters
		$skin = Media::clearPath($skin);

		// path to skin
		$skinPath = dirname(__FILE__).'/../'.cfg::DIR_SKINS.cfg::get('skin').$skin.self::SKIN_SUFFIX;

		// skin directory
		$skinSQL = rtrim(cfg::get('skin'),'/');

		// cache skins from DB
		static $dbSkin = array();
		if (count($dbSkin) == 0) {
			$sql = db::query("SELECT `id`,`skin` FROM %t", "skins");
			while ($row = db::fetchObject($sql)) {
				$dbSkin[$row->id] = $row->skin;
			}
			db::free($sql);
		}

		if (is_file($skinPath) && $dbSkin[$skin] == $skinSQL) {
			return true;
		} else {
			return false;
		}
	}
}
